import { Select } from 'antd';
import { get, set } from 'lodash';
import { useEffect, useId, useMemo, useSyncExternalStore } from 'react';
import { ComponentProps } from 'react';

import DxInput from './DxInput';

export const widgets = {
  input: DxInput,
  select: Select,
} as const;
export type FieldItem = {
  label?: React.ReactNode;
  prop: string;
} & {
  [K in keyof typeof widgets]: { widget: K; props?: ComponentProps<(typeof widgets)[K]> };
}[keyof typeof widgets];
const store = new Map<string, Record<string, any>>();
const storeDispath = new Map<string, Set<Function>>();

export default function useForm(model: Record<string, any> = {}) {
  const id = useId();
  useMemo(() => {
    store.set(id, model);
  }, [id, model]);

  useEffect(() => {
    return () => {
      store.delete(id);
    };
  }, [id]);

  return id;
}
function setValue(id: string, path: string[], value: any) {
  const model = store.get(id) || {};
  const dispathStore = storeDispath.get(path.join('.'));
  set(model, path, value);
  if (dispathStore) {
    dispathStore.forEach((cb) => {
      cb();
    });
  }

  return model;
}
export function useFormField(id: string, path: string[]) {
  const fieldId = path.join('.');
  const value = useSyncExternalStore(
    (callback: () => any) => {
      const tmp = storeDispath.get(fieldId);
      if (!tmp) {
        storeDispath.set(fieldId, new Set([callback]));
      } else {
        tmp.add(callback);
      }

      return () => {
        storeDispath.get(fieldId)?.delete(callback);
      };
    },
    () => get(store.get(id), path)
  );

  return [value, (value: any) => setValue(id, path, value)];
}
